package org.cfx.gift.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.commons.lang.StringUtils;
import org.cfx.gift.client.AuthClient;
import org.cfx.gift.constants.BaseContans;
import org.cfx.gift.domain.LoginUser;
import org.cfx.gift.domain.User;
import org.cfx.gift.domain.UserInfo;
import org.cfx.gift.dto.UserPhoneRegisterDto;
import org.cfx.gift.exception.BusinessException;
import org.cfx.gift.exception.azzert.RonghuaAssert;
import org.cfx.gift.exception.code.ResponseCode;
import org.cfx.gift.mapper.UserInfoMapper;
import org.cfx.gift.mapper.UserMapper;
import org.cfx.gift.service.IUserService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.cfx.gift.util.AjaxResult;
import org.cfx.gift.util.CodeGenerateUtils;
import org.cfx.gift.util.MD5Utils;
import org.cfx.gift.util.VerifyCodeUtils;
import org.dromara.sms4j.aliyun.config.AlibabaFactory;
import org.dromara.sms4j.api.SmsBlend;
import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.enumerate.SupplierType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.validation.Valid;
import java.time.Duration;
import java.util.Date;
import java.util.UUID;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author cfx
 * @since 2023-10-31
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Qualifier("org.cfx.gift.client.AuthClient")
    @Autowired
    private AuthClient authClient;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserInfoMapper userInfoMapper;

    /** 获取单租户模式实例*/
    private final SmsBlend aliSms = SmsFactory.createSmsBlend(SupplierType.ALIBABA);

    @Override
    public String sendRegisterVerifyCode(String phone) {
        // 1 参数检验
        // 1.1 非空
        if (StringUtils.isBlank(phone)) throw new RuntimeException("手机号不能为空！");
        // 1.2 手机号是否存在  存在就不用发短信验证码
        int count = super.selectCount(new EntityWrapper<User>().eq("phone", phone));
        if (count > 0) {
            throw new RuntimeException("手机号已存在，请直接登录！");
        }
        //2 生成验证码
        //3.生成随机手机4位验证码，保存到redis
        //区分验证码的功能性，应加上codeType
        String phoneCode = VerifyCodeUtils.generateVerifyCode(4, "0123456789");
        System.out.println("验证码是："+phoneCode);
        String key = BaseContans.USER_REGISTER_SMS_CODE_REDIS_KEY + ":" + phone;
        String codeInRedis = (String) redisTemplate.opsForValue().get(key);
        if (codeInRedis!=null){
            //已经发送过
            long oldTime = Long.parseLong(codeInRedis.split(":")[1]);
            if(System.currentTimeMillis()-oldTime<60*1000){
                //两次发送的时间间隔小于一分钟
                throw new BusinessException("发送过于频繁，请稍后再试");
            }
            //把验证码重置为redis里面存储的内容
            phoneCode =codeInRedis.split(":")[0];
        }
//        boolean send = SendSMSUtil.send(phoneCode, registerDto.getPhone());
//        if (send){
//            redisTemplate.opsForValue().set(key,phoneCode+":"+System.currentTimeMillis(),Duration.ofMinutes(5));
//            return new AjaxResult();
//        }
        redisTemplate.opsForValue().set(key,phoneCode+":"+System.currentTimeMillis(), Duration.ofMinutes(5));
        //        阿里云向此手机号发送短信
        //阿里云向此手机号发送短信
        SmsResponse smsResponse = SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(phone, phoneCode);
        System.out.println(smsResponse);
        System.out.println(smsResponse.isSuccess());
        return phoneCode;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public void registerByPhone(UserPhoneRegisterDto registerDto) {
        //1 参数检验
        // 1.1 手机验证码校验
        String key = BaseContans.USER_REGISTER_SMS_CODE_REDIS_KEY + ":" + registerDto.getPhone();
        String codeInRedis = (String) redisTemplate.opsForValue().get(key);
        //如果redis里的验证码为空，证明没有发生过
        RonghuaAssert.isNotBlank(codeInRedis, ResponseCode.RESPONSE_CODE_40003);
        assert codeInRedis != null;
        String code = codeInRedis.split(":")[0];
        //判断code是否和前端传过来的一致
        System.out.println("前端传过来的验证码："+registerDto.getVerifyCode());
        System.out.println("redis里的验证码："+code);
        RonghuaAssert.isEq(registerDto.getVerifyCode(),code,ResponseCode.RESPONSE_CODE_40005);
        //2 调用auth服务，保存t_login_user信息 @TODO
        //加盐值
        String salt = UUID.randomUUID().toString();

        String byMd5 = MD5Utils.encrypByMd5("cfx" + registerDto.getPassword() + salt + "2000");

        //保存auth信息
        LoginUser loginUser = new LoginUser();
        loginUser.setPhone(registerDto.getPhone());
        loginUser.setType(0);
        loginUser.setSalt(salt);
        loginUser.setPassword(byMd5);
        AjaxResult ajaxResult = authClient.addOrUpdate(loginUser);
        // 如果调授权服务异常，就报错
        if (!ajaxResult.isSuccess()){
            throw new BusinessException(ajaxResult.getMessage());
        }

        //3 保存git_user 库中的t_user 和 t_user_info
        User user = new User();
        user.setPhone(registerDto.getPhone());
        //加密
        System.out.println(salt);
        System.out.println(registerDto.getPassword());
        user.setPassword(byMd5);
        user.setSalt(salt);
        user.setSecLevel(1);
        user.setBitState(1L);
        //因为是远程调用，所有要从ajaxResult里面获取resultObj里面的数据
        Long resultObjId = Long.parseLong(ajaxResult.getResultObj().toString());

        user.setLoginId(resultObjId);
        super.insert(user);

        //保存详情
        UserInfo userInfo = new UserInfo();
        userInfo.setRegTime(System.currentTimeMillis());
        userInfo.setLevel(0);
        userInfo.setGrowScore(0);
        userInfo.setUserId(user.getId());
        userInfoMapper.insert(userInfo);
        //4 注册成功后发送短信或邮件，提示用户
//        rabbitTemplate.convertAndSend(RegisterNoticeRabbitmqConfig.EXCHANGE_TOPICS_INFORM,
//                "inform.sms",
//                new RegisterNoticeDto(registerDto.getPhone(),"收到短信通知：你好！你注册的账号已经完成，可以正常使用了！"));  //收件人
//        阿里云向此手机号发送短信
//        SmsResponse smsResponse = SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(registerDto.getPhone(), "注册成功！");
//        System.out.println(smsResponse);
//        System.out.println(smsResponse.isSuccess());
//        System.out.println(1/0);

    }

    @Override
    public User getByLoginId(Long id) {
        return userMapper.getByLoginId(id);
    }
}
